#ifndef UnlimitedNumber_h
#define UnlimitedNumber_h
#include <string>
#include <exception>

class UnlimitedNumber{
public: // Арифметические методы
   UnlimitedNumber & operator += (const UnlimitedNumber & n);
   inline UnlimitedNumber & operator -= (const UnlimitedNumber & n);
   UnlimitedNumber & operator *= (UnlimitedNumber n);
   UnlimitedNumber & operator /= (const UnlimitedNumber & n);

   //"Служебные" методы
   
   //VL internal integer types couldn't be constructed from string, use explicit or operator >> from istream
   //VL use const ref to pass string object
   //SNMA: Я не согласен, т.к. в дальнейшем мне нужна (уж такой конструктор я написал) редактируемая копия
   //SNMA: а explicit'а не было, т.к. на момент, когда я писал этот код по заданию А. Смаля, я такого пока не знал и нигде не проходил
   explicit UnlimitedNumber(std::string str = "");
   std :: istream & operator >> (std :: istream & is);

   //VL same as from-string constructor
   explicit UnlimitedNumber(const char * cstr); //SNMA: Честно говоря, не вижу смысла в этом конструкторе. Может, убрать?

   UnlimitedNumber(const UnlimitedNumber & n);

   UnlimitedNumber(long long l);
   ~UnlimitedNumber();
   
   void swap (UnlimitedNumber & n);

   UnlimitedNumber & operator = (UnlimitedNumber const & n);

   std::string get()const;

private: // Данные
   typedef unsigned char data_type;
   
   
   static const unsigned int step = 2;
   static const data_type impossible_value = 100; // минимальное значение, недопустимое в элементах data; Равно 10 в степени step. Указано, т.к. нет желания вычислять его постоянно, когда оно нужно
   
   //VL use std::vector instead
   size_t size_;
   data_type * data_; // Массив с числом, по сути - хранение числа в "100-ичной" системе счисления, каждый элемент массива - 100-ичная цифра. data[0] - наименьший разряд
   bool is_positive_;

private: //Закрытые от пользователя методы

   UnlimitedNumber & unsigned_multiply(UnlimitedNumber & n)const;
   UnlimitedNumber & divide_in_half(); //Деление надвое
   UnlimitedNumber & redouble(); //Удвоение
   bool is_even()const; //Провверка на чётность
   inline bool is_zero()const; //Проверка на равенство нулю
   void resize(size_t newsize_);
   void actualize_size();

   static long long get_incorrect_data_num(data_type const * data, size_t size);
   
   friend bool operator == (UnlimitedNumber const & a, UnlimitedNumber const & b);
   friend bool operator < (UnlimitedNumber const & a, UnlimitedNumber const & b);
   
   //VL why do you pass UnlimitedNumber by value?
   friend UnlimitedNumber operator - (UnlimitedNumber n); //SNMA: Унарный минус, нужна изменяемая копия
   friend UnlimitedNumber operator / (UnlimitedNumber a, UnlimitedNumber b); //SNMA: А тут мне аналогично нужны изменяемые значения. В операторах +, -, * изменяемое значение второго аргумента не нужно.
};

bool operator == (UnlimitedNumber const & a, UnlimitedNumber const & b);
bool operator != (UnlimitedNumber const & a, UnlimitedNumber const & b);
bool operator < (UnlimitedNumber const & a, UnlimitedNumber const & b);
bool operator > (UnlimitedNumber const & a, UnlimitedNumber const & b);
bool operator <= (UnlimitedNumber const & a, UnlimitedNumber const & b);
bool operator >= (UnlimitedNumber const & a, UnlimitedNumber const & b);
UnlimitedNumber operator + (UnlimitedNumber a, UnlimitedNumber const & b);
UnlimitedNumber operator - (UnlimitedNumber a, UnlimitedNumber const & b);
UnlimitedNumber operator * (UnlimitedNumber a, UnlimitedNumber const & b);
UnlimitedNumber operator / (UnlimitedNumber a, UnlimitedNumber b);
std::ostream & operator << (std::ostream & ostr, UnlimitedNumber const & n);
UnlimitedNumber operator - (UnlimitedNumber n);

#endif
